home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / man / dev.fmt / pdev.man < prev    next >
Encoding:
Text File  |  1990-08-14  |  28.8 KB  |  729 lines

  1.  
  2.  
  3.  
  4. PDEV                         Devices                         PDEV
  5.  
  6.  
  7.  
  8. _________________________________________________________________
  9.  
  10. NNAAMMEE
  11.      Pseudo-devices - files controlled by server processes.
  12.  
  13. _________________________________________________________________
  14.  
  15. IINNTTRROODDUUCCTTIIOONN
  16.      A pseudo-device is a special file that is  controlled  by  a
  17.      user-level  process,  which  is  called  its _s_e_r_v_e_r.  To all
  18.      other  processes,  called  _c_l_i_e_n_t_s,  the  pseudo-device   is
  19.      accessed  like  an  ordinary  file  or  device using regular
  20.      Sprite system calls.  This allows  user-level  processes  to
  21.      emulate  a  file  or  device with arbitrary characteristics.
  22.      Pseudo-devices are used in Sprite  for  terminal  emulation,
  23.      access  to Internet protocols, the stream communication used
  24.      by the window system, and for the user-level  implementation
  25.      of other services.
  26.  
  27.      This document describes how to write  server  programs  that
  28.      control  pseudo-devices  using  the  raw  kernel  interface.
  29.      There is also a Pdev library package that takes care of most
  30.      of these details.  See the Pdev man page for details.
  31.  
  32.      A pseudo-device server is much like an RPC server; it  waits
  33.      for  requests, performs some task, and returns results.  The
  34.      server has a _s_e_r_v_i_c_e _s_t_r_e_a_m for each client that has  opened
  35.      the  pseudo-device.  Each time the client makes an operation
  36.      on the pseudo-device the kernel maps this  into  a  request-
  37.      response  exchange  over  the service stream.  The remaining
  38.      sections describe this protocol in more detail.  (The header
  39.      file /sprite/lib/include/dev/pdev.h contains the type defin-
  40.      itions repeated here, and describes the Fs_IOControl() calls
  41.      mentioned here in more detail.)
  42.  
  43. CCOONNTTRROOLL SSTTRREEAAMM
  44.      The server of a pseudo-device is established by opening  the
  45.      pseudo-device  with  the O_MASTER flag.  This returns a _c_o_n_-
  46.      _t_r_o_l _s_t_r_e_a_m to the server process.  The  server  listens  on
  47.      the  control stream for messages issued when client open the
  48.      pseudo-device.
  49.  
  50.        #include <sys/file.h>
  51.        #include <dev/pdev.h>
  52.  
  53.        cntrlStreamID = open("_p_s_e_u_d_o-_d_e_v_i_c_e", O_MASTER | O_RDONLY, 0666);
  54.  
  55.      The server's open  call  will  fail  with  the  FS_FILE_BUSY
  56.      status  if there is already a server process controlling the
  57.      pseudo device.  Similarly, a client's open  will  fail  with
  58.      DEV_OFFLINE  if  there  is no server process controlling the
  59.      pseudo-device.
  60.  
  61.      The server establishes contact with a client in a  two  part
  62.  
  63.  
  64.  
  65. Sprite v.1.0        Printed:  August 14, 1990                   1
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72. PDEV                         Devices                         PDEV
  73.  
  74.  
  75.  
  76.      process.  First, it reads a Pdev_Notify message off the con-
  77.      trol stream that indicates the streamID of the  new  service
  78.      stream  used  to communicate with the client.  In the second
  79.      phase, the server responds to an initial  PDEV_OPEN  request
  80.      on the new service stream.  The server's response determines
  81.      if the client's open operation will succeed or fail.   Refer
  82.      to  the  following  section on the request-response protocol
  83.      for examples that use the control stream and  handle  client
  84.      requests.
  85.  
  86.  
  87. RREEQQUUEESSTT--RREESSPPOONNSSEE
  88.      Whenever a client invokes an operation on the  pseudo-device
  89.      (Fs_Read,  Fs_Write, Fs_IOControl, Fs_Close) the kernel for-
  90.      wards it to the server process so the server  can  implement
  91.      it  in  any  way  it chooses.  This is done using a request-
  92.      response protocol much like a Remote Procedure  Call  (RPC).
  93.      The  kernel  packages  up the parameters of the system call,
  94.      passes them to the server  process  in  a  _r_e_q_u_e_s_t  _m_e_s_s_a_g_e,
  95.      blocks the client process until a _r_e_p_l_y _m_e_s_s_a_g_e is returned,
  96.      and unpackages the return parameters from the reply message.
  97.      This is transparent to the client, but not to the server.
  98.  
  99.      This is the format of the request and reply messages:
  100.  
  101.      typedef struct {
  102.          unsigned int magic;       /* PDEV_REQUEST_MAGIC or PFS_REQUEST_MAGIC */
  103.          int operation;            /* What action is requested. */
  104.          int messageSize;          /* The complete size of the request header
  105.                                     * plus data, plus padding for alignment */
  106.          int requestSize;          /* Size of data following this header */
  107.          int replySize;            /* Max size of the reply data expected. */
  108.          int dataOffset;           /* Offset of data from start of header */
  109.      } Pdev_RequestHdr;
  110.  
  111.      typedef struct {
  112.          Pdev_RequestHdr hdr;      /* with PDEV_REQUEST_MAGIC */
  113.          union {                   /* Additional parameters to the operation. */
  114.              Pdev_OpenParam open;
  115.              Pdev_RWParam read;
  116.              Pdev_RWParam write;
  117.              Pdev_IOCParam ioctl;
  118.              Pdev_SetAttrParam setAttr;
  119.          } param;
  120.          /*
  121.           * Data, if any, follows.
  122.           */
  123.      } Pdev_Request;
  124.  
  125.      typedef struct Pdev_Reply {
  126.          unsigned int magic;       /* == PDEV_REPLY_MAGIC */
  127.          int status;               /* Return status of remote call */
  128.  
  129.  
  130.  
  131. Sprite v.1.0        Printed:  August 14, 1990                   2
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138. PDEV                         Devices                         PDEV
  139.  
  140.  
  141.  
  142.          int selectBits;           /* Return select state bits */
  143.          int replySize;            /* Size of the data in replyBuf, if any */
  144.          Address replyBuf;         /* Server space address of reply data */
  145.          int reserved;             /* Room for future expansion */
  146.      } Pdev_Reply;
  147.  
  148.  
  149.      The server does not read the request messages directly  from
  150.      the  service  stream.   Instead,  there  is a _r_e_q_u_e_s_t _b_u_f_f_e_r
  151.      associated with each service stream that is in the  server's
  152.      own   address  space.   The  kernel  puts  request  messages
  153.      directly into this buffer.  Access to  the  buffer  is  syn-
  154.      chronized  using  two pointers, _f_i_r_s_t_B_y_t_e and _l_a_s_t_B_y_t_e.  The
  155.      server reads the values of these pointers from  the  service
  156.      stream,  and  can safely examine the request(s) found in the
  157.      request buffer between firstByte  and  lastByte.   When  the
  158.      server  is done with requests it updates firstByte by making
  159.      an Fs_IOControl() call (IOC_PDEV_SET_PTRS)  on  the  request
  160.      stream.
  161.  
  162.      The kernel fills the request buffer circularly,  and  it  is
  163.      possible  that  more  than one request will be found between
  164.      firstByte and lastByte.   This  occurs  if  write-behind  is
  165.      enabled (see below), or if the client process forks and both
  166.      processes use their duplicated stream to the  pseudo-device.
  167.      As  a  convenience  to  servers,  the  kernel  never wraps a
  168.      request message  around  the  end  of  the  request  buffer.
  169.      Instead,  if  the  request  buffer fills up the kernel waits
  170.      until the server has  processed  all  the  request  messages
  171.      before  resetting and adding messages starting at the begin-
  172.      ning of the buffer.
  173.  
  174.      Three example procedures follow.   The  first,  GetClient(),
  175.      reads  the control stream and sets up the new request stream
  176.      and its associated request  buffer.   The  second,  Serve(),
  177.      illustrates  the  use  of  _f_i_r_s_t_B_y_t_e and _l_a_s_t_B_y_t_e.  The last
  178.      one, Reply(), uses Fs_IOControl to return the reply message.
  179.      Fuller  examples  can be found in the Pdev library code, see
  180.      /sprite/src/lib/c/etc/pdev.c.
  181.  
  182.      /*
  183.       * _G_e_t_C_l_i_e_n_t _r_e_t_u_r_n_s _t_h_e _s_t_r_e_a_m_I_D _f_o_r _a _n_e_w _r_e_q_u_e_s_t _s_t_r_e_a_m.
  184.       */
  185.      int
  186.      GetClient(cntrlStreamID, reqBufSize)
  187.          int cntrlStreamID;
  188.          int reqBufSize;
  189.      {
  190.          Pdev_SetBufArgs setBuf;
  191.          Pdev_Notify notify;
  192.          int amountRead;
  193.          int newStreamID;
  194.  
  195.  
  196.  
  197. Sprite v.1.0        Printed:  August 14, 1990                   3
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204. PDEV                         Devices                         PDEV
  205.  
  206.  
  207.  
  208.          /*
  209.           * _R_e_a_d _t_h_e _c_o_n_t_r_o_l _s_t_r_e_a_m _t_o _g_e_t _a _n_e_w _r_e_q_u_e_s_t _s_t_r_e_a_m.
  210.           * (_Y_o_u _s_h_o_u_l_d _c_h_e_c_k _t_h_e _r_e_t_u_r_n _f_r_o_m _F_s__R_e_a_d _a_n_d _v_e_r_i_f_y
  211.           *  _t_h_e _m_a_g_i_c _n_u_m_b_e_r _i_n _t_h_e _P_d_e_v__N_o_t_i_f_y _s_t_r_u_c_t_u_r_e.)
  212.           */
  213.          Fs_Read(cntrlStreamID, sizeof(Pdev_Notify), (Address) ¬ify, &amountRead);
  214.          newStreamID = notify.streamID;
  215.          /*
  216.           * _A_l_l_o_c_a_t_e _t_h_e _r_e_q_u_e_s_t _b_u_f_f_e_r, _a_n_d _t_e_l_l _t_h_e _k_e_r_n_e_l _a_b_o_u_t _i_t.
  217.           */
  218.          setBuf.requestBufAddr = Mem_Alloc(reqBufSize);
  219.          setBuf.requestBufSize = reqBufSize;
  220.          setBuf.readBufAddr = 0;
  221.          setBuf.readBufSize = 0;
  222.          Fs_IOControl(newStreamID, IOC_PDEV_SET_BUF, sizeof(Pdev_SetBufArgs),
  223.                  (Address)&setBuf, 0, 0);
  224.          return(newStreamID);
  225.      }
  226.  
  227.      Serve(requestStream, requestBuffer)
  228.          int requestStream;
  229.          Address requestBuffer;
  230.      {
  231.          Pdev_BufPtrs bufPtrs;
  232.          int amountRead;
  233.          Pdev_Request *requestMsg;
  234.  
  235.          /*
  236.           * _R_e_a_d _t_h_e _f_i_r_s_t_B_y_t_e _a_n_d _l_a_s_t_B_y_t_e _p_o_i_n_t_e_r_s.
  237.           * (_Y_o_u _s_h_o_u_l_d _c_h_e_c_k _t_h_e _r_e_t_u_r_n _f_r_o_m _F_s__R_e_a_d _a_n_d _v_e_r_i_f_y
  238.           *  _t_h_e _m_a_g_i_c _n_u_m_b_e_r _i_n _t_h_e _P_d_e_v__B_u_f_P_t_r_s _s_t_r_u_c_t_u_r_e.)
  239.           */
  240.          Fs_Read(requestStreamID, sizeof(Pdev_BufPtrs), &bufPtrs, &amountRead);
  241.          while (bufPtrs.requestFirstByte < bufPtrs.requestLastByte) {
  242.                  /*
  243.                   * _C_a_s_t _a _p_o_i_n_t_e_r _t_o _t_h_e _r_e_q_u_e_s_t _m_e_s_s_a_g_e.
  244.                   * (_Y_o_u _s_h_o_u_l_d _v_e_r_i_f_y _t_h_e _m_a_g_i_c _n_u_m_b_e_r _i_n _t_h_e _P_d_e_v__R_e_q_u_e_s_t.)
  245.                   */
  246.                  requestMsg = (Pdev_Request *)&requestBuffer[bufPtrs.requestFirstByte];
  247.                  switch (requestMsg->hdr.operation) {
  248.                  /*
  249.                   * _S_w_i_t_c_h _o_u_t _t_o _o_p_e_r_a_t_i_o_n _s_p_e_c_i_f_i_c _c_o_d_e _h_e_r_e...
  250.                   */
  251.                  }
  252.                  bufPtrs.requestFirstByte += requestMsg->hdr.messageSize;
  253.          }
  254.          /*
  255.           * _M_o_v_e _t_h_e _f_i_r_s_t_B_y_t_e _p_o_i_n_t_e_r _p_a_s_t _t_h_e _p_r_o_c_e_s_s_e_d _r_e_q_u_e_s_t _m_e_s_s_a_g_e_s.
  256.           */
  257.          Fs_IOControl(requestStreamID, IOC_PDEV_SET_PTRS, sizeof(Pdev_BufPtrs), &bufPtrs, 0, 0);
  258.      }
  259.  
  260.  
  261.  
  262.  
  263. Sprite v.1.0        Printed:  August 14, 1990                   4
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270. PDEV                         Devices                         PDEV
  271.  
  272.  
  273.  
  274.      Reply(requestStream, status, selectBits, replyBuf)
  275.          int requestStream;
  276.          ReturnStatus status;
  277.          Address replyBuf;
  278.      {
  279.          Pdev_Reply reply;
  280.          /*
  281.           * _F_o_r_m_a_t _a_n_d _r_e_t_u_r_n _t_h_e _r_e_p_l_y _m_e_s_s_a_g_e.
  282.           */
  283.          reply.magic = PDEV_REPLY_MAGIC;
  284.          reply.status = status;
  285.          reply.selectBits = selectBits;
  286.          reply.replySize = replySize;
  287.          reply.replyBuf = replyBuf;
  288.          Fs_IOControl(requestStream, IOC_PDEV_REPLY, sizeof(Pdev_Reply), (Address)&reply, 0, 0);
  289.      }
  290.  
  291.      Let's review before moving on to select,  write-behind,  and
  292.      read  buffering.   The  control  stream is returned when the
  293.      server opens the pseudo-device using the O_MASTER  flag.   A
  294.      service  stream  is created each time a client process opens
  295.      the pseudo-device, and it is used by the  server  to  handle
  296.      requests  from  that  client.   The server reads the control
  297.      stream to get new service stream IDs.  The  kernel  forwards
  298.      client operations on the pseudo-device to the server using a
  299.      request-response protocol.   The  protocol  uses  a  request
  300.      buffer in the server's address space, and an associated pair
  301.      of pointers, firstByte and lastByte.  There is  one  request
  302.      buffer  and pair of pointers per service stream.  The server
  303.      reads new values of firstByte and lastByte from the  service
  304.      stream.   After  it is done with the request(s) found in the
  305.      request  buffer   the   server   updates   firstByte   using
  306.      IOC_PDEV_SET_PTRS.    Replies   are  returned  with  another
  307.      Fs_IOControl(), IOC_PDEV_REPLY.
  308.  
  309. SSEELLEECCTT AANNDD AASSYYNNCCHHRROONNOOUUSS II//OO
  310.      Note that the select  operation  is  not  forwarded  to  the
  311.      server.   It  is too costly to switch out to the server pro-
  312.      cess each time a client process makes a select that includes
  313.      a  stream to a pseudo-device.  Instead, the kernel maintains
  314.      some select bits for each request stream (one bit  each  for
  315.      readability,  writability,  and  exceptional conditions) and
  316.      checks this state itself.  The server updates the state bits
  317.      each time it replies, or by making by using IOC_PDEV_READY.
  318.  
  319.      The sever can optimize writes to the pseudo-device  by  ena-
  320.      bling  write-behind.   With  write-behind enabled the kernel
  321.      does not block the client waiting for a  reply  to  a  write
  322.      request.   Instead,  the write is assumed to have succeeded,
  323.      and the client can  continue  to  write  until  the  request
  324.      buffer  fills  up.   This  reduces  the  number  of  context
  325.      switches made when handling writes to be proportional to the
  326.  
  327.  
  328.  
  329. Sprite v.1.0        Printed:  August 14, 1990                   5
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336. PDEV                         Devices                         PDEV
  337.  
  338.  
  339.  
  340.      amount  of  data  written,  instead  of  proportional to the
  341.      number of write calls by the  client.   If  write-behind  is
  342.      enabled    the   operation   code   for   writes   will   be
  343.      PPDDEEVV__WWRRIITTEE__AASSYYNNCC  instead  of  PPDDEEVV__WWRRIITTEE.   Note  that  the
  344.      server has to accept all data written (there is no opportun-
  345.      ity for an error return), and it does not return a reply  to
  346.      write   requests.    Write-behind   is   enabled  using  the
  347.      IOC_PDEV_WRITE_BEHIND Fs_IOControl() call.  The input buffer
  348.      for this Fs_IOControl() should contain a boolean which indi-
  349.      cates whether or not write behind is enabled.
  350.  
  351.      The server can optimize  reads  from  the  pseudo-device  by
  352.      using  a  read buffer.  The read buffer is used in a similar
  353.      way as the request buffer.  In this case the server  process
  354.      adds  data  to  the read buffer as it becomes available, and
  355.      the kernel removes data in response to client read requests.
  356.      Again,  this  reduces  the number of context switches to the
  357.      server process.  Like the request buffer, the read buffer is
  358.      in  the server's address space.  The IOC_PDEV_SET_BUF iocon-
  359.      trol() call is used to  declare  both  buffers.   Its  input
  360.      buffer  contains  a Pdev_SetBufArgs structure.  Synchroniza-
  361.      tion over the read buffer is also done  with  _f_i_r_s_t_B_y_t_e  and
  362.      _l_a_s_t_B_y_t_e pointers.  (The Pdev_BufPtrs structure that is read
  363.      from the service stream contains a  firstByte-lastByte  pair
  364.      for  both  the request and read buffers.) The kernel updates
  365.      readFirstByte as the client  process  reads  data,  and  the
  366.      server  process  updates readLastByte as its adds data.  The
  367.      IOC_PDEV_SET_PTR iocontrol() call is used by the  server  to
  368.      set  both  readLastByte  and requestFirstByte.  An important
  369.      convention is that -1 (minus one) means  ``no  change''  and
  370.      can  safely be passed in for either readLastByte or request-
  371.      FirstByte.  Another important convention is that the  server
  372.      should  reset  and  begin  filling  the read buffer from the
  373.      beginning after it empties.  The server  knows  when  it  is
  374.      empty  when it reads (-1,-1) for readFirstByte and readLast-
  375.      Byte.
  376.  
  377. RREEGGUULLAARR OOPPEERRAATTIIOONNSS
  378.      The following short sections describes the different request
  379.      messages  that the server will receive.  They each have some
  380.      extra parameters, and may require  special  actions  on  the
  381.      part of the server.
  382.  
  383.      PDEV_OPEN
  384.  
  385.             typedef struct Pdev_OpenParam {
  386.               int flags;                /* Flags from the Fs_Open call */
  387.               Proc_PID pid;             /* Client's process ID */
  388.               int hostID;               /* Host ID where client is from */
  389.               int uid;                  /* User ID of the client process */
  390.               Fmt_Format format;        /* Defines byte order of client machine */
  391.               int reserved;             /* Reserved for future expansion */
  392.  
  393.  
  394.  
  395. Sprite v.1.0        Printed:  August 14, 1990                   6
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402. PDEV                         Devices                         PDEV
  403.  
  404.  
  405.  
  406.             } Pdev_OpenParam;
  407.  
  408.           This is the first request to arrive on  a  new  service
  409.           stream  when  a  client  opens the pseudo-device.  (The
  410.           kernel waits until the request buffer is  declared,  of
  411.           course, before issuing this request.) The client's open
  412.           call will block  until  the  server  responds  to  this
  413.           request.   The reply status returned by the server will
  414.           be the return status of the Fs_Open call by the client.
  415.           The  request parameters include a process ID and a user
  416.           ID of the client so the server can  do  authentication.
  417.           The format parameter is used in conjuction with library
  418.           routines to handle byte swapping of  data  blocks  sent
  419.           and received with the PDEV_IOCTL command.
  420.  
  421.  
  422.      PDEV_CLOSE
  423.           A client has closed the device. This is the  last  mes-
  424.           sage  that  will  arrive  on  the service stream so the
  425.           server should close the service stream.  There  are  no
  426.           close specific parameters in the request header.
  427.  
  428.  
  429.      PDEV_READ
  430.  
  431.             typedef struct {
  432.               int offset;               /* Read/Write byte offset */
  433.               unsigned int familyID;    /* Process group ID */
  434.               Proc_PID procID;          /* Process ID */
  435.               int reserved;             /* Extra */
  436.             } Pdev_RWParam;
  437.  
  438.           A client is requesting request.replySize bytes of  data
  439.           from  the  pseudo-device.   The read request parameters
  440.           include a byte offset at which  the  read  should  take
  441.           place,  and the process's familyID which can be used to
  442.           enforce the notion of a controlling process  group  for
  443.           the   pseudo-device.    The  amount  of  data  actually
  444.           returned should be  set  in  reply.replySize,  and  the
  445.           status  of  the read should be set in reply.status.  An
  446.           end-of-file  on  the  pseudo-device  is  indicated   by
  447.           returning  zero bytes and a SUCCESS status.  If no data
  448.           is   available   the   server   should    return    the
  449.           FS_WOULD_BLOCK  status.   In  this case the kernel will
  450.           block the client process until the server indicates the
  451.           pseudo-device  is readable by making the IOC_PDEV_READY
  452.           iocontrol() call:
  453.  
  454.               bits = FS_WRITABLE | FS_READABLE;/* _a_s _a_p_p_r_o_p_r_i_a_t_e... */
  455.               status = Fs_IOControl(streamID, IOC_PDEV_READY, sizeof(int),
  456.                                         (Address)&bits, 0, 0;
  457.  
  458.  
  459.  
  460.  
  461. Sprite v.1.0        Printed:  August 14, 1990                   7
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468. PDEV                         Devices                         PDEV
  469.  
  470.  
  471.  
  472.           This will unblock the client process and cause  another
  473.           FS_PDEV_READ request to arrive on the service stream.
  474.  
  475.           Note that the server will not see PDEV_READ requests if
  476.           it  has  enabled  read-ahead.  Read-ahead is implicitly
  477.           enabled if the IOC_PDEV_SET_BUF iocontrol() call  indi-
  478.           cates a non-zero sized read-ahead buffer.
  479.  
  480.  
  481.      PDEV_WRITE
  482.           A client is writing data  to  the  pseudo-device.   The
  483.           amount   of   data   being   written  is  indicated  in
  484.           request.requestSize, and the write parameters  are  the
  485.           same  as  those for read: they include an offset, and a
  486.           familyID, and a processID.  The  data  written  follows
  487.           the  request header immediately.  The reply information
  488.           on a synchronous write is  an  integer  containing  the
  489.           number of bytes accepted by the server.  The server can
  490.           accept some (or none) of  the  data  being  written  by
  491.           returning   FS_WOULD_BLOCK  and  the  number  of  bytes
  492.           accepted.  The server unblocks the client  process  (as
  493.           described    above    for   FS_PDEV_READ)   using   the
  494.           IOC_PDEV_READY iocontrol().
  495.  
  496.           The semantics of returning FS_WOULD_BLOCK are important
  497.           because the Sprite kernel takes care of blocking client
  498.           processes and retrying write operations until the  full
  499.           amount  of  data  is  transferred to the pseudo-device,
  500.           unless the stream is set to  non-blocking,  of  course.
  501.           To  repeat,  the  write  service  routine should return
  502.           FS_WOULD_BLOCK if it doesn't accept all the data  given
  503.           to it.
  504.  
  505.  
  506.      PDEV_WRITE_SYNC
  507.           If write-behind is enabled then this operation code  is
  508.           issued  instead  of  PPDDEEVV__WWRRIITTEE.  The message format is
  509.           the same for both synchronous and asynchronous  writes.
  510.           The  important  difference  is  that  the server has to
  511.           accept all of the data and it does not return a  reply.
  512.           Thus asynchronous writes implicitly succeed.
  513.  
  514.  
  515.      PDEV_IOCONTROL
  516.  
  517.               typedef struct {
  518.                                         int command;/* iocontrol() command #. */
  519.                                         unsigned int familyID;/* Can be used to enforce controlling tty */
  520.                                         Proc_PID procID;/* Process ID of client */
  521.                                         int byteOrder;/* Defines client's byte ordering */
  522.                                         int reserved;/* Extra */
  523.               } Pdev_IOCParam;
  524.  
  525.  
  526.  
  527. Sprite v.1.0        Printed:  August 14, 1990                   8
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534. PDEV                         Devices                         PDEV
  535.  
  536.  
  537.  
  538.           A client is doing some device-specific operation.   The
  539.           Fs_IOControl  parameters  include the client's command,
  540.           an inBuffer, and an outBuffer.  The server  process  is
  541.           free  to  define  and implement any command it desires.
  542.           For example, the Internet protocol pseudo-devices  sup-
  543.           ports  commands  to  bind  to addresses, accept connec-
  544.           tions, etc.
  545.  
  546. BBYYTTEE OORRDDEERRIINNGG IISSSSUUEESS
  547.      In order to correctly support clients executing on  machines
  548.      with  a  different  byte order than their server, the format
  549.      field is used to define the client's byte order.  A  set  of
  550.      library routines is available to byte swap the block of data
  551.      that follows the  PDEV_IOCTL  message  header.   It  is  the
  552.      servers  responsibility to byte swap the input data block of
  553.      the PDEV_IOCTL command, and to byte  swap  the  return  data
  554.      block.   This  is not an issue with reads and writes because
  555.      the data is assumed to be a string of characters.
  556.  
  557.  
  558. PPSSEEUUDDOO--FFIILLEE--SSYYSSTTEEMM SSUUPPPPOORRTT
  559.      Pseudo-device connections  can  be  made  into  pseudo-file-
  560.      systems  when  files  in  the pseudo-file-system are opened.
  561.      The pseudo-device connection is exactly as described in this
  562.      manual,  except  that  the connection is created differently
  563.      using the IIOOCC__PPFFSS__OOPPEENN  command  on  the  pseudo-file-system
  564.      naming  service  stream.   (See  the  devices pfs man page.)
  565.      Additionally, however, there are two  operations  concerning
  566.      attributes  that appear in the request stream.  These opera-
  567.      tions are only made on pseudo-device connections to  pseudo-
  568.      file-system servers.
  569.  
  570.  
  571.      PDEV_GET_ATTR
  572.           This is used to get the  attributes  of  a  file  in  a
  573.           pseudo-file-system.   There  are no extra input parame-
  574.           ters  to  this  call.   The   returned   data   is   an
  575.           FFss__AAttttrriibbuutteess record.
  576.  
  577.  
  578.      PDEV_SET_ATTR
  579.  
  580.           typedef struct {
  581.               int flags;                /* Which attributes to set */
  582.               int uid;                  /* User ID */
  583.               int gid;                  /* Group ID */
  584.           } Pdev_SetAttrParam;
  585.  
  586.      This is used to set  certain  attributes  of  a  file  in  a
  587.      pseudo-file-system.  The ffllaaggss parameter is a combination of
  588.      FFSS__SSEETT__TTIIMMEESS, FFSS__SSEETT__MMOODDEE,  FFSS__SSEETT__OOWWNNEERR,  FFSS__SSEETT__FFIILLEE__TTYYPPEE,
  589.      FFSS__SSEETT__DDEEVVIICCEE  that  indicates  what attributes to set.  The
  590.  
  591.  
  592.  
  593. Sprite v.1.0        Printed:  August 14, 1990                   9
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600. PDEV                         Devices                         PDEV
  601.  
  602.  
  603.  
  604.      uuiidd and ggiidd identify the calling process and should be  used
  605.      to  check  permissions.   A FFss__AAttttrriibbuutteess record follows the
  606.      request message header  and  contains  the  new  attributes.
  607.      There is no return data for this call.
  608.  
  609.  
  610. SSEERRVVEERR II//OO CCOONNTTRROOLLSS
  611.      The server uses a number of IOC_PDEV  iocontrol()  calls  to
  612.      implement  its part of the request-response protocol.  These
  613.      are summarized here, although the  header  file  pdev.h  can
  614.      also be consulted.
  615.  
  616.      IOC_PDEV_SET_BUF
  617.           This is used to  tell  the  kernel  where  the  request
  618.           buffer  and  read  ahead buffer (if any) are. The input
  619.           buffer should contain a Pdev_SetBufArgs struct.
  620.  
  621.      IOC_PDEV_WRITE_BEHIND
  622.           Set  (Unset)  write-behind  buffering  in  the  request
  623.           buffer.   The  single  input argument is a pointer to a
  624.           Boolean; TRUE enables write-behind, FALSE inhibits  it.
  625.           The default is no write-behind.
  626.  
  627.      IOC_PDEV_BIG_WRITES
  628.           Set (Unset) the ability of the client to write a  chunk
  629.           larger  than will fit into the request buffer.  This is
  630.           to support UDP socket semantics that prevent  a  client
  631.           from  writing  more than the declared packet size.  The
  632.           input buffer should reference a Boolean;  TRUE  enables
  633.           big  writes  (which  is the default) FALSE prevents big
  634.           writes.  The default is to  allow  big  writes.   Large
  635.           client  write requests are broken up by the server into
  636.           write requests that will fit into the  request  buffer.
  637.           The  request  stream  is  locked during this so that no
  638.           other client operations can slip in.
  639.  
  640.      IOC_PDEV_SET_PTRS
  641.           This is used  to  update  the  firstByte  and  lastByte
  642.           pointers  into the request and read ahead buffers.  The
  643.           input buffer is a Pdev_BufPtrs structure.
  644.  
  645.      IOC_PDEV_REPLY
  646.           This is used to send a reply to a request.   The  input
  647.           buffer contains a Pdev_Reply.  This includes an address
  648.           (in the server's space) of a  buffer  containing  reply
  649.           data, if any.
  650.  
  651.      IOC_PDEV_READY
  652.           The server uses this to  notify  the  kernel  that  the
  653.           pseudo-device  is  ready for I/O now.  The input buffer
  654.           should contain an  int  with  an  or'd  combination  of
  655.           FS_READABLE, FS_WRITABLE, or FS_EXCEPTION.
  656.  
  657.  
  658.  
  659. Sprite v.1.0        Printed:  August 14, 1990                  10
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666. PDEV                         Devices                         PDEV
  667.  
  668.  
  669.  
  670.      IOC_PDEV_SIGNAL_OWNER
  671.           The server uses this to signal the  owning  process  or
  672.           process  group.   The  input  buffer  is  a PPddeevv__SSiiggnnaall
  673.           record containing a ssiiggnnaall and ccooddee field.   The  owner
  674.           gets  established  by  a IOC_SET_OWNER operation on the
  675.           client end of the pseudo-device connection.
  676.  
  677.  
  678. FFIILLEESS
  679.      /sprite/lib/include/dev/pdev.h-pseudo-device definitions
  680.  
  681. SSEEEE AALLSSOO
  682.      Pdev, pfs, Fs_Open, Fs_Close, Fs_Read, Fs_Write,  Fs_Select,
  683.      Fs_IOControl, Fs_EventHandlerCreate, Bit
  684.  
  685. KKEEYYWWOORRDDSS
  686.      pseudo-device, device, server, client, read,  write,  iocon-
  687.      trol
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725. Sprite v.1.0        Printed:  August 14, 1990                  11
  726.  
  727.  
  728.  
  729.